<script setup lang="ts">
import axios from "axios";
import { nextTick, onMounted, reactive, ref, watch } from "vue";
import * as echarts from "echarts";
import China from "../geojson/china.json";
import VChart from "./VChart.vue";
import type { GeoJSON } from "echarts/types/src/coord/geo/geoTypes.d.ts";
import iconVppUser from "./icon-vpp-user.png";
import { getHomeVppUserList } from "@/api/home";
import { useRouter } from "vue-router";
const router = useRouter();
const mapDemoTwo = ref(null);
// echarts.registerMap("山东省", shandong as GeoJSON);
echarts.registerMap("China", China as GeoJSON);
let data = China.features.map(item => {
  return {
    name: item.properties.name,
    value: item.properties.adcode
  };
});
const props = defineProps({
  isDark: {
    type: Boolean,
    default: false
  }
});
const emit = defineEmits(["wheel"]);

function gaussianBlur(context, radius) {
  var pixels,
    weight,
    alpha,
    r,
    g,
    b,
    a,
    width = context.canvas.width,
    height = context.canvas.height;

  radius = radius || 5;
  weight = 1 / (2 * radius + 1);
  pixels = context.getImageData(0, 0, width, height);
  alpha = context.createImageData(width, height);

  for (var y = 0; y < height; y += 1) {
    for (var x = 0; x < width; x += 1) {
      var area = 0,
        red = 0,
        green = 0,
        blue = 0,
        alphaPixel = 0;

      for (var i = -radius; i <= radius; i += 1) {
        var ix = x + i;
        var iy = y + i;

        if (ix >= 0 && ix < width && iy >= 0 && iy < height) {
          var pixel = getPixel(pixels, ix, iy);
          area += weight;
          red += pixel[0] * weight;
          green += pixel[1] * weight;
          blue += pixel[2] * weight;
          alphaPixel += pixel[3] * weight;
        }
      }

      alpha.data[y * width * 4 + x * 4] = red / area;
      alpha.data[y * width * 4 + x * 4 + 1] = green / area;
      alpha.data[y * width * 4 + x * 4 + 2] = blue / area;
      alpha.data[y * width * 4 + x * 4 + 3] = alphaPixel / area;
    }
  }

  context.putImageData(alpha, 0, 0);

  function getPixel(pixels, x, y) {
    var pos = (y * width + x) * 4;
    return [
      pixels.data[pos],
      pixels.data[pos + 1],
      pixels.data[pos + 2],
      pixels.data[pos + 3]
    ];
  }
}

const createHTML = async () => {
  return new Promise((resolve, reject) => {
    let width = mapDemoTwo.value.offsetWidth;
    let height = mapDemoTwo.value.offsetHeight;
    const canvas = document.createElement("canvas");
    canvas.width = width;
    canvas.height = height;
    const ctx = canvas.getContext("2d");
    ctx.save();
    // ctx.filter = "blur(.5px)";
    // let hgradient = ctx.createLinearGradient(0, 0, width, 0);
    //
    // if (props.isDark) {
    //   hgradient.addColorStop(0, "#000");
    //   hgradient.addColorStop(0.5, "#fff");
    //   hgradient.addColorStop(1, "#000");
    // } else {
    //   hgradient.addColorStop(0, "#fff");
    //   hgradient.addColorStop(0.5, "#000");
    //   hgradient.addColorStop(1, "#fff");
    // }
    // let hlen = parseInt(height / 70);
    // for (let i = 0; i < hlen; i++) {
    //   ctx.beginPath();
    //   ctx.moveTo(70, (i + 1) * 70);
    //   ctx.lineTo(width - 70, (i + 1) * 70);
    //   ctx.strokeStyle = hgradient;
    //   ctx.lineWidth = 0.2;
    //   ctx.stroke();
    // }
    // let cgradient = ctx.createLinearGradient(0, 0, 0, height);
    //
    // if (props.isDark) {
    //   cgradient.addColorStop(0, "#000");
    //   cgradient.addColorStop(0.5, "#fff");
    //   cgradient.addColorStop(1, "#000");
    // } else {
    //   cgradient.addColorStop(0, "#fff");
    //   cgradient.addColorStop(0.5, "#000");
    //   cgradient.addColorStop(1, "#fff");
    // }
    // ctx.strokeStyle = cgradient;
    // let len = parseInt(width / 70);
    // for (let i = 0; i < len; i++) {
    //   ctx.beginPath();
    //   ctx.moveTo(70 + i * 70, 0);
    //   ctx.lineTo(70 + i * 70, height);
    //   ctx.lineWidth = 0.2;
    //   if (i === 0 || i === len - 1) {
    //     ctx.strokeStyle = "#fff";
    //   } else {
    //     ctx.strokeStyle = cgradient;
    //   }
    //   ctx.stroke();
    // }
    // var c2gradient = ctx.createRadialGradient(
    //   width / 2,
    //   height / 2,
    //   0,
    //   width / 2,
    //   height / 2,
    //   height
    // );
    // if (props.isDark) {
    //   c2gradient.addColorStop(0, "#fff");
    //   c2gradient.addColorStop(0.5, "#ccc");
    //   c2gradient.addColorStop(1, "#000");
    // } else {
    //   c2gradient.addColorStop(0, "#000");
    //   c2gradient.addColorStop(0.5, "#ccc");
    //   c2gradient.addColorStop(1, "#fff");
    // }
    // ctx.fillStyle = c2gradient;
    // for (let i = 0; i < len; i++) {
    //   for (let j = 0; j < hlen; j++) {
    //     ctx.beginPath();
    //     ctx.arc(140 + i * 70, 70 + j * 70, 2, 0, 2 * Math.PI);
    //     ctx.fill();
    //   }
    // }
    // // 恢复原始状态
    // ctx.restore();

    ctx.fillStyle = props.isDark ? "#182855" : "#FFFFFF";
    ctx.fillRect(0, 0, width, height);
    // const img = document.createElement("img");
    // img.src = mapDi;
    // img.onload = () => {
    //   ctx.fillRect(0, 0, width, height);
    //   ctx.drawImage(img, 0, 0, width, height);
    //   resolve(canvas);
    // };

    resolve(canvas);
  });
};

// const points = [
//   // [120.38623, 36.267067] // 青岛机场
// ];
// const citys = [
//   [120.38264000000004, 36.067082] // 青岛
// ];
let scale = ref(0.9);
// let geoDatas = ref([
//   {
//     data: data,
//     geoJson: shandong,
//     value: {
//       name: "山东省",
//       value: 370000
//     }
//   }
// ]);
let geoDatas = ref([
  {
    data: data,
    geoJson: China,
    value: {
      name: "中国",
      value: 100000
    }
  }
]);
let level = 0;
let option = ref({
  // backgroundColor: "#030528",
  backgroundColor: {
    image: null, // 支持为 HTMLImageElement, HTMLCanvasElement，不支持路径字符串
    repeat: "no-repeat" // 是否平铺，可以是 'repeat-x', 'repeat-y', 'no-repeat'
  },
  geo: [
    {
      show: true,
      silent: false,
      map: "China",
      // aspectScale: 1,
      zoom: scale.value, // 缩放
      zlevel: 0,
      layoutCenter: ["50%", "70%"],
      layoutSize: "155%",
      roam: true,
      label: {
        show: true,
        color: "#fff",
        emphasis: {
          show: true,
          color: "#fff"
        }
      },
      itemStyle: {
        normal: {
          borderColor: "#c0f3fb",
          areaColor: {
            // image: mapDiN,
            image: null,
            repeat: "repeat"
          }
        }
      },
      emphasis: {
        disabled: false,
        itemStyle: {
          borderColor: "#c0f3fb",
          borderWidth: 4,
          areaColor: {
            // image: mapDiH,
            image: null,
            repeat: "repeat"
          },
          opacity: 0.8
        }
      },
      nameProperty: "name",
      regions: data
    }
  ],
  series: [
    {
      // 动效散点公共配置项
      silent: false, // 暂不支持鼠标交互
      type: "effectScatter",
      coordinateSystem: "geo",
      rippleEffect: {
        //涟漪特效
        period: 8, //动画时间，值越小速度越快
        brushType: "fill", //波纹绘制方式 stroke, fill
        scale: 2.4 //波纹圆环最大限制，值越大波纹越大
      },
      label: {
        normal: {
          show: true,
          position: "right", //显示位置
          offset: [5, 0], //偏移设置
          formatter: function (params) {
            //圆环显示文字
            return params.data.name;
          },
          fontSize: 16,
          color: "#fff"
        },
        emphasis: {
          show: true
        }
      },
      symbol: "image://" + iconVppUser,
      symbolSize: 16,
      itemStyle: {
        normal: {
          show: false,
          borderWidth: 1,
          color: "rgba(255, 86, 11, 1)"
        }
      },
      data: []
    }
  ]
});
const createBg = async () => {
  return new Promise((resolve, reject) => {
    let width = 600;
    let height = 600;
    const canvas = document.createElement("canvas");
    canvas.width = width;
    canvas.height = height;
    const ctx = canvas.getContext("2d");
    let grd = ctx.createRadialGradient(
      width / 2,
      height / 2,
      0,
      width / 2,
      height / 2,
      height
    );
    grd.addColorStop(0, "#0065db");
    grd.addColorStop(1, "#1a4bb7");
    ctx.fillStyle = grd;
    ctx.fillRect(0, 0, width, height);
    resolve(canvas);
  });
};
const createBgGrid = async () => {
  return new Promise((resolve, reject) => {
    let width = 600;
    let height = 600;
    const canvas = document.createElement("canvas");
    canvas.width = width;
    canvas.height = height;
    const ctx = canvas.getContext("2d");
    let grd = ctx.createRadialGradient(
      width / 2,
      height / 2,
      0,
      width / 2,
      height / 2,
      height
    );
    grd.addColorStop(0, "#0065db");
    grd.addColorStop(1, "#1a4bb7");
    ctx.fillStyle = grd;
    ctx.fillRect(0, 0, width, height);
    let len = 30;
    for (let i = 0; i < len; i++) {
      ctx.beginPath();
      ctx.moveTo(0, (i * 600) / len);
      ctx.lineTo(600, (i * 600) / len);
      ctx.setLineDash([4, 4]);
      ctx.lineWidth = 0.2;
      ctx.strokeStyle = "rgb(0,0,0)";
      ctx.stroke();
    }
    for (let i = 0; i < len; i++) {
      ctx.beginPath();
      ctx.moveTo((i * 600) / len, 0);
      ctx.lineTo((i * 600) / len, 600);
      ctx.setLineDash([4, 4]);
      ctx.lineWidth = 0.2;
      ctx.strokeStyle = "rgb(0,0,0)";
      ctx.stroke();
    }
    resolve(canvas);
  });
};
const setBg = async () => {
  const myBg = await createHTML();
  option.value.backgroundColor.image = myBg;
  const mapDiN = await createBg();
  option.value.geo[0].itemStyle.normal.areaColor.image = mapDiN;
  const mapDiH = await createBgGrid();
  option.value.geo[0].emphasis.itemStyle.areaColor.image = mapDiH;
};
const allUser = reactive({
  data: []
});
const setCharts = () => {
  let data = allUser.data.filter(i => {
    return i.latitude && i.longitude;
  });
  let showData = [];
  data.forEach(item => {
    showData.push({
      name: item.name,
      value: [item.longitude, item.latitude, item.id]
    });
  });
  option.value.series[0].data = showData;
};
const getAllUserVpp = async () => {
  let data = await getHomeVppUserList();
  allUser.data = data;
  setCharts();
};
const mapMouseover = e => {
  if (e.componentSubType && e.componentSubType === "effectScatter") {
    emit("dataShow", {
      show: true,
      data: allUser.data.find(i => i.id === e.data.value[2])
    });
  } else {
    emit("dataShow", { show: false, data: null });
  }
};
const mapMarkerClick = e => {
  if (e.componentSubType && e.componentSubType === "effectScatter") {
    // emit("vppUserMarkerClick", {
    //   id: e.data.value[2]
    // });
    router.push({
      path: "/station/predictingTrends",
      query: {
        id: e.data.value[2]
      }
    });
  }
};
onMounted(async () => {
  await setBg();
  await getAllUserVpp();
});
const screenResize = async () => {
  await nextTick();
  await setBg();
};
const myChartView = ref(null);
watch(
  () => props.isDark,
  n => {
    setBg();
  },
  {
    deep: true
  }
);
const mapLoading = ref(false);
const mapDblClick = async vdata => {
  mapLoading.value = true;
  if (level === 0) {
    if (vdata.value === 370000 || vdata.value === 440000) {
      // 全国向山东下转
      level = level + 1;
      // let sd = await import(`../geojson/${vdata.value}.json`);
      let sd = await axios.get(
        `https://geo.datav.aliyun.com/areas_v3/bound/${vdata.value}_full.json`
      );
      data = sd.data.features.map(item => {
        return {
          name: item.properties.name,
          value: item.properties.adcode
        };
      });
      geoDatas.value.push({
        data: data,
        geoJson: sd.data,
        value: {
          name: vdata.name,
          value: vdata.value
        }
      });
      echarts.registerMap(
        vdata.name,
        geoDatas.value[geoDatas.value.length - 1].geoJson as GeoJSON
      );
      option.value.geo[0].map = vdata.name;
      option.value.geo[0].regions = data;
      option.value.geo[0].layoutCenter = ["50%", "50%"];
      setTimeout(() => {
        mapLoading.value = false;
      }, 300);
    } else {
      mapLoading.value = false;
    }
  } else {
    if (level === 3) {
      mapLoading.value = false;
      return;
    } else {
      level = level + 1;
    }
    let v = null;
    if (level === 3) {
      v = await axios.get(
        `https://geo.datav.aliyun.com/areas_v3/bound/${vdata.value}.json`
      );
    } else {
      v = await axios.get(
        `https://geo.datav.aliyun.com/areas_v3/bound/${vdata.value}_full.json`
      );
    }
    // let child = await import(`./data/${vdata.value}.json`);
    let child = v.data;
    data = child.features.map(item => {
      return {
        name: item.properties.name,
        value: item.properties.adcode
      };
    });
    geoDatas.value.push({
      data: data,
      geoJson: child,
      value: {
        name: vdata.name,
        value: vdata.value
      }
    });
    echarts.registerMap(
      vdata.name,
      geoDatas.value[geoDatas.value.length - 1].geoJson as GeoJSON
    );
    option.value.geo[0].map = vdata.name;
    option.value.geo[0].regions = data;
    option.value.geo[0].layoutCenter = ["50%", "50%"];
    setTimeout(() => {
      mapLoading.value = false;
    }, 300);
  }
};
const contextmenu = e => {
  mapLoading.value = true;
  if (level === 0) {
    mapLoading.value = false;
    return;
  } else {
    level = level - 1;
  }
  geoDatas.value.pop();
  echarts.registerMap(
    geoDatas.value[geoDatas.value.length - 1].value.name,
    geoDatas.value[geoDatas.value.length - 1].geoJson as GeoJSON
  );
  option.value.geo[0].map =
    geoDatas.value[geoDatas.value.length - 1].value.name;
  option.value.geo[0].regions = geoDatas.value[geoDatas.value.length - 1].data;
  if (level === 0) {
    option.value.geo[0].layoutCenter = ["50%", "70%"];
  }
  setTimeout(() => {
    mapLoading.value = false;
  }, 300);
};
</script>

<template>
  <div ref="mapDemoTwo" class="map-demo">
    <v-chart
      ref="myChartView"
      v-loading="mapLoading"
      :element-loading-background="'rgba(0,0,0,.4)'"
      style="flex: 1; flex-shrink: 1; overflow: hidden"
      :options="option"
      @contextmenu="contextmenu"
      @dblClick="mapDblClick"
      @mouseover="mapMouseover"
      @uclick="mapMarkerClick"
      @resize="screenResize"
    />
  </div>
</template>
<style lang="scss" scoped>
.map-demo {
  display: flex;
  flex-direction: column;
  width: calc(100% - 370px);
  overflow: hidden;
}
</style>
